<?php


namespace lib\model;
use lib\basic\PdoTool;

class Query {
    protected $db = null;
    protected $where = "";
    protected $joins = [];
    protected $on = "";
    protected $fields = "";
    protected $table = "";
    protected $orderBy = "";
    protected $limit = "";
    protected $set = "";
    protected $action = ""; //select update delete
    protected $sql = "";

    /**
     * @param array $conds = [
     *  "id = 1",
     *  "id" => 1
     * ]
     * @return $this
     */
    public function where ($conds = []) {
        $this->where = trim($this->where);
        $type = gettype($conds);
        if ($type == "string") {
            $this->where = $conds;
        } elseif ($type == "array") {
            foreach ($conds as $k => $cond) {
                if (is_numeric($k)) {
                    $this->where = $this->where ? $this->where . " and {$cond}" : $cond;
                } else {
                    $this->where = $this->where ? $this->where . " and {$k} = '{$cond}'" : "{$k} = '{$cond}'";
                }
            }
        }

        return $this;
    }

    public function andWhere ($conds = []) {
        $where = "";
        $type = gettype($conds);
        if ($type == "string") {
            $where = $where ? $where . " {$conds}" : $conds;
        } elseif ($type == "array") {
            foreach ($conds as $k => $cond) {
                if (is_numeric($k)) {
                    $where = $where ? $where . " {$cond}" : $cond;
                } else {
                    $where = $where ? $where . " and {$k} = '{$cond}'" : "{$k} = '{$cond}'";
                }
            }
        }
        $this->where .= " and ({$where})";

        return $this;
    }

    public function orWhere ($conds = []) {
        $where = "";
        $type = gettype($conds);
        if ($type == "string") {
            $where = $where ? $where . " {$conds}" : $conds;
        } elseif ($type == "array") {
            foreach ($conds as $k => $cond) {
                if (is_numeric($k)) {
                    $where = $where ? $where . " {$cond}" : $cond;
                } else {
                    $where = $where ? $where . " and {$k} = '{$cond}'" : "{$k} = '{$cond}'";
                }
            }
        }
        $this->where .= " or ({$where})";

        return $this;
    }

    public function fields ($fields = "*") {
        $this->fields = $fields;
        return $this;
    }

    public function from ($table) {
        $this->table = $table;
        return $this;
    }

    public function leftJoin ($table, $on = "") {
        $join[] = "left join " . $table;
        if ($on) $join[] = "on " . $on;
        $this->joins[] = $join;
        return $this;
    }

    public function innerJoin ($table, $on = "") {
        $join[] = "inner join " . $table;
        if ($on) $join[] = "on " . $on;
        return $this;
    }

    /**
     * @param string $orderBy
     * @return $this
     */
    public function orderBy ($orderBy = "") {
        $this->orderBy = $this->orderBy ? $this->orderBy . " and " . $orderBy : "order by " . $orderBy;
        return $this;
    }

    /**
     * @param $offset 如果$rows 不传或为空，则$offset为$rows值
     * @param null $rows
     */
    public function limit ($offset, $rows = null) {
        $n = func_num_args();
        if ($n == 2) {
            $this->limit = "limit {$offset}, {$rows}";
        } else {
            $this->limit = "limit {$offset}";
        }

        return $this;
    }

    /**
     * update table set a = 1, b = 2 ...中的set
     * @param array $attrs
     * @return $this
     */
    public function set($attrs = []) {
        foreach ($attrs as $key => $value) {
            $this->set .= $this->set ? ", {$key} = '{$value}'" : "set {$key} = '{$value}'";
        }
        return $this;
    }

    /**
     * @return string
     */
    public function getSql () {
        $sql = $this->action;

        if ($this->action == "select") {
            $sql .= $this->fields ? " {$this->fields}" : " *";
            $sql .= $this->table ? " from {$this->table}" : "";
            foreach ((array)$this->joins as $join) {
                $sql .= " {$join[0]}";
                if (count($join) == 2) {
                    $sql .= " {$join[1]}";
                }
            }
        } elseif ($this->action == "update") {
            $sql .= " {$this->table}" . " {$this->set}";
        } elseif ($this->action == "delete") {
            $sql .= " {$this->table}";
        } else {
            $sql .= " {$this->table}";
        }

        $sql .= $this->where ? " where {$this->where}" : "";
        $sql .= " {$this->orderBy}";
        $sql .= " {$this->limit}";
        $this->sql = $sql;
        return $this->sql;
    }

    /**
     * @return string
     */
    public function select () {
        $this->action = "select";
        return $this->getSql();
    }

    /**
     * @param $table
     * @return string
     */
    public function update ($table) {
        $this->action = "update";
        $this->table = $table;
        return $this->getSql();
    }

    /**
     * @param $table
     * @return string
     */
    public function delete ($table) {
        $this->action = "update";
        $this->table = $table;
        return $this->getSql();
    }

    /**
     * @param $table
     * @param array $attrs
     */
    public function insert ($table, $attrs = []) {
        $str1 = "";
        $str2 = "";
        foreach ($attrs as $key => $value) {
            $str1 = $str1 ? ",{$key}" : $key;
            $str2 = $str2 ? ",{$value}" : $value;
        }
        return $this->sql = "insert into {$table} ({$str1}) values ({$str2})";
    }
}

/**
 * $conds = ['id = 1', 'id' => 1, 'level' => ['>', 10]]
 */